// -----------------------------
// Author: 		Dhaenens Gert	
// Creation: 	10/22/2014 12:12:45 PM				
// -----------------------------

#include "AudioManager.h"

#include "Application.h"
#include "FileManager.h"
#include "Sound.h"

extern "C"
{
	FMOD_RESULT F_API FMOD_Debug_SetMode(unsigned int mode, unsigned int buffersize);
}

AudioManager::AudioManager()
: m_lpSystem(nullptr)
{
}

AudioManager::~AudioManager()
{
	if (m_lpSystem)
		m_lpSystem->release();
}

Bool AudioManager::Init(Application* lpApp)
{
	UInt32 maxChannels = 32;
	Log::WriteLine(_T("[AUDIO]\t\tMax Channels: %u"), maxChannels);

	// Create the AudioManager System
	FMOD_RESULT r = FMOD::System_Create(&m_lpSystem);
	if (r != FMOD_OK)
		return false;
	// Initialize the System
	UINT uFlags = FMOD_INIT_NORMAL;
	r = m_lpSystem->init(maxChannels, uFlags, NULL);
	if (r != FMOD_OK)
		return false;

	return true;
}
void AudioManager::Update(Application* lpApp)
{
	if (m_lpSystem)
		m_lpSystem->update();
}

Sound* AudioManager::CreateSoundFromFile(Application* lpApp, const TString& Identifier)
{
	TString Path = lpApp->GetFiles()->GetFileName(Identifier);
	Log::WriteLine(_T("[AUDIO]\t\tLoading Sound from File \"%s\""), Identifier.c_str());

	std::string aStr = std::string(Path.begin(), Path.end());
	FMOD::Sound* lpSound = nullptr;
	FMOD_RESULT r = m_lpSystem->createSound(aStr.c_str(), FMOD_HARDWARE | FMOD_LOOP_OFF, NULL, &lpSound);
	if (r != FMOD_OK)
	{
		Log::WriteLine(_T("[SOUND]\t\tERROR: Could not load Sound from File \"%s\" (Identifier: %s)"), Path.c_str(), Identifier.c_str());
		return nullptr;
	}
	return new Sound(lpSound, this);
}
Sound* AudioManager::CreateSoundFromData(Application* lpApp, Float* lpSamples, UInt32 sampleCount, UInt32 channelCount)
{
	// Create the Sound Desc
	FMOD_CREATESOUNDEXINFO sndInfo = {};
	sndInfo.cbsize = sizeof(sndInfo);
	sndInfo.length = sampleCount * sizeof(Float);
	sndInfo.numchannels = channelCount;
	sndInfo.format = FMOD_SOUND_FORMAT_PCMFLOAT;
	sndInfo.defaultfrequency = 32000;

	// Reinterpret the Samples as const Char
	const Char* lpData = reinterpret_cast<const Char*>(lpSamples);

	// Create the Sound
	FMOD::Sound* lpSound = nullptr;
	FMOD_RESULT r = m_lpSystem->createSound(lpData, FMOD_HARDWARE | FMOD_LOOP_OFF | FMOD_OPENMEMORY | FMOD_OPENRAW, &sndInfo, &lpSound);
	if (r != FMOD_OK)
	{
		Log::WriteLine(_T("[SOUND]\t\tERROR: Failed to create Sound from Memory."));
		return nullptr;
	}
	return new Sound(lpSound, this);
}
Sound* AudioManager::CreateSoundFromData8Bit(Application* lpApp, Byte* lpSamples, UInt32 sampleCount, UInt32 channelCount)
{
	// Create the Sound Desc
	FMOD_CREATESOUNDEXINFO sndInfo = {};
	sndInfo.cbsize = sizeof(sndInfo);
	sndInfo.length = sampleCount * sizeof(Byte);
	sndInfo.numchannels = channelCount;
	sndInfo.format = FMOD_SOUND_FORMAT_PCM8;
	sndInfo.defaultfrequency = 32000;

	// Reinterpret the Samples as const Char
	const Char* lpData = reinterpret_cast<const Char*>(lpSamples);

	// Create the Sound
	FMOD::Sound* lpSound = nullptr;
	FMOD_RESULT r = m_lpSystem->createSound(lpData, FMOD_HARDWARE | FMOD_LOOP_OFF | FMOD_OPENMEMORY | FMOD_OPENRAW, &sndInfo, &lpSound);
	if (r != FMOD_OK)
	{
		Log::WriteLine(_T("[SOUND]\t\tERROR: Failed to create Sound from Memory."));
		return nullptr;
	}
	return new Sound(lpSound, this);
}